#pragma once

#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

using namespace EpollModule;

using connection_t = std::shared_ptr<Connection>;

class Reactor
{
    const static int event_num = 64;

private:
    // 检测该listensockfd对应的连接是否存在
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

public:
    Reactor() : _isrunning(false), _epoller(std::make_unique<Epoller>())
    {
        _epoller->Init();
    }

    // 从外部传递fd,把连接中涉及的方法也注册进去，创建对应的Epoll
    // void InsertConnection(int sockfd, func_t recver, func_t sender, func_t excepter)
    // 直接插入新连接
    void InsertConnection(connection_t conn)
    {
        auto iter = _connections.find(conn->Sockfd());
        if (iter == _connections.end())
        {
            _connections.insert(std::make_pair(conn->Sockfd(), conn));
            // 将新插入的连接(对应的fd),写透到内核的epoll中。
            // 此处的fd是listensockfd
            _epoller->Add(conn->Sockfd(), conn->GetEvents());
            // 设置关联关系，让connection回指当前对象
            conn->SetOwner(this);
            LOG(LogLevel::DEBUG) << "add connection success: " << conn->Sockfd();
        }
    }
    void EnableReadWrite(int sockfd, bool readable, bool writeable)
    {
        if (IsConnectionExists(sockfd))
        {
            //修改用户层connection的事件
            uint32_t events = ((readable ? EPOLLIN : 0) | (readable ? EPOLLOUT : 0) | EPOLLET);
            _connections[sockfd]->SetEvents(events);
            //写透到内核中
            _epoller->Update(sockfd, _connections[sockfd]->GetEvents());
        }
    }
    void DelConnection(int sockfd)
    {
        if(IsConnectionExists(sockfd))
        {
            //1.从内核中移除对sockfd的关心
            _epoller->Delete(sockfd);
            //2.关闭特定的文件描述符
            _connections[sockfd]->Close();
            //3.从_connections中移除对应的connection
            _connections.erase(sockfd);

        }
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, event_num, timeout);
        Dispatcher(n);
    }
    void Dispatcher(int n)
    {
        for (int i = 0; i < n; ++i)
        {
            // 开始进行派发,派发给指定的模块
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            // 将异常事件转换为读写事件
            if (revents & EPOLLERR || (revents & EPOLLHUP))
            {
                revents = (EPOLLIN | EPOLLOUT);
            }

            if ((revents & EPOLLIN) && IsConnectionExists(sockfd))
            {
                _connections[sockfd]->Recver();
            }
            if ((revents & EPOLLOUT) && IsConnectionExists(sockfd))
            {
                _connections[sockfd]->Recver();
            }
        }
    }

    void DebugPrint()
    {
        std::cout << "Epoller 管理的fd: ";
        for (auto &iter : _connections)
        {
            std::cout << iter.first << " ";
        }
        std::cout << std::endl;
    }
    void Loop()
    {
        _isrunning = true;
        int timeout = -1;
        while (_isrunning)
        {
            LoopOnce(timeout);
            DebugPrint();
            //可以在此处进行超时管理
            //可能出现对于某一个连接长时间不进行任何操作
            //那么需要对其进行管理
            //
        }
        _isrunning = false;
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~Reactor()
    {
    }

private:
    std::unique_ptr<Epoller> _epoller;
    // 采用fd，Connect这种方式来管理建立的连接
    std::unordered_map<int, connection_t> _connections; // 管理服务器内部所有的连接
    bool _isrunning;

    struct epoll_event _revs[event_num];
};